<template>
  <el-dialog v-model="dialogVisible" title="数据源编辑" top="80px">
    <el-card>
      <el-form label-width="80px" :model="dataSource">
        <el-form-item label="数据连接">
          <el-select v-model="dataSource.repositoryId">
            <el-option v-for="(item,index) in repositories" :key="index" :label="item.name"
                       :value="item.id"></el-option>
          </el-select>
          <el-button type="text" @click="loadRepositories">重新加载选项</el-button>
        </el-form-item>
        <el-row>
          <label class="el-form-item__label" style="width: 80px;">查询语句</label>
          <el-button type="text" icon="el-icon-question" circle @click="openVn">帮助</el-button>
        </el-row>
        <el-row>
          <el-input v-model="dataSource.syntax" type="textarea" :rows="8"></el-input>
        </el-row>

        <label class="el-form-item__label" style="width: 80px;">数据预览</label>
        <el-row>
          <ex-slot :row-header="tableData.tableHeader" :data="tableData.tableList"></ex-slot>
        </el-row>
      </el-form>
    </el-card>
    <span class="dialog-footer">
      <el-button size="mini" @click="previewData" type="warning">预览数据</el-button>
      <el-button size="mini" @click="save" type="success">保存</el-button>
      <el-button size="mini" @click="confirm" type="primary">确定</el-button>
      <el-button size="mini" @click="close">取消</el-button>
    </span>
  </el-dialog>
</template>

<script>
import {saveDataSource, getDataQuery} from '@/api/dataSource';
import {getList} from "@/api/repositorySource";
import exSlot from '@/components/tableview/simple';
import {onMounted, ref} from "vue";

export default {
  name: "edit",
  components: {exSlot},
  setup(props) {
    const repositories = ref([]);
    const loadRepositories = async () => {
      let resp = await getList();
      repositories.value = resp.data.records
    }
    onMounted(() => {
      loadRepositories()
    })

    return {
      repositories, loadRepositories
    }
  },
  data() {
    return {
      dialogVisible: false,
      tableData: {
        tableList: [],
        tableHeader: []
      },
      dataSource: {},
      show: true
    }
  },
  methods: {
    open(data) {
      this.dataSource = Object.assign({}, data);
      this.tableData.tableHeader = this.dataSource.preDataFields;
      this.tableData.tableList = []
      return new Promise((resolve, reject) => {
        this.dialogVisible = true;
        this.resolve = resolve;
        this.reject = reject;
      })
    },
    //确认
    confirm() {
      this.dialogVisible = false
      this.resolve(this.dataSource)
    },
    //预览
    previewData() {
      const _this = this
      const request = {
        repositorySourceId: this.dataSource.repositoryId,
        dataProviderType: this.dataSource.dataProviderType,
        fields: [],
        relations: [],
        filters: [],
        sql: this.dataSource.syntax,
        limit: {take: 10, offset: 0},
        queryType: 1,
        preFilterSql: this.dataSource.preDataFields,
        beforeExecute: this.dataSource.beforeExecute,
        Comments: "加载预览数据",
        noCache: true
      }
      getDataQuery(request, function (data) {
        _this.dataSource.preDataFields = _this.tableData.tableHeader = _this.extractFields(data)
        _this.tableData.tableList = data
      });
    },
    //保存
    save() {
      //保存数据源
      if (!this.dataSource.syntax) {
        this.$message.warning("查询语句内容不能为空");
        return false;
      }
      if (!this.tableData.tableList.length) {
        this.$message.warning("请先预览出结果再保存");
        return false;
      }
      this.$prompt('给数据源命个名', {
        inputValue: this.dataSource.name,
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(({value}) => {
        this.dataSource.name = value
        let item = this.repositories.find(t => {
          console.info(this.dataSource)
          return t.id == this.dataSource.repositoryId
        })
        if (item) {
          this.dataSource.dataProviderType = item.dataProviderType;
        }
        return saveDataSource(this.dataSource)
      }).then(() => {
        this.$message.success("数据源保存成功！")
        this.confirm()
      })
    },
    //取消
    close() {
      this.dialogVisible = false;
      this.reject("diag is cancel.");
    },
    //查看提示
    openVn() {
      this.$message({
        dangerouslyUseHTMLString: true,
        message: '<strong>语句编写注意事项:</strong><br>1.只支持select语句；<br>2.结尾请勿添加排序；<br>3.请勿添加数据行限制，例如top或limit；<br>4.请勿写分组或聚合'
      })
    },
    extractFields(data) {
      const fields = [];
      if (data && data.length) {
        var toprow = data[0];
        for (var k in toprow) {
          if (k === "rownum") {
            continue;
          }
          var rd = toprow[k];
          var field = {
            name: k,
            dataType: this.getDataType(rd),
            systemName: k
          }
          fields.push(field);
          //当首行的指定字段值为空时，扫描当前列以确定准确数据类型
          if (rd == "" || rd == null || rd == undefined) {
            var row = data.find(function (d) {
              return d[k];
            });
            if (row) {
              field.dataType = this.getDataType(row[k]);
            }
          }
        }
      }
      return fields;
    },
    //分析出数据类型
    getDataType(val) {
      if (this.isDate(val)) {
        return 4;
      }
      if (typeof val === "string" || typeof val === "boolean" || val == undefined || val == null) {
        return 1;
      }
      if (typeof val === "number") {
        return 2;
      }
    },
    // 判断一个字符串是不是时间格式
    isDate(str) {
      if (typeof str == 'date') {
        return true
      }
      if (typeof str == 'string') {
        let results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) *$/);
        if (results && results.length > 3) return true;
        results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2}) *$/);
        if (results && results.length > 6) return true;
        results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2})\.(\d{1,9}) *$/);
        if (results && results.length > 7) return true;
      }
      return false;
    }
  }
}
</script>

<style scoped>

</style>
